﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Serialization;
using System.Xml;

namespace HJ212_Common
{
    /// <summary>
    /// 对象序列化/反序列化类
    /// </summary>
    /// <typeparam name="T">对象的类型</typeparam>
    public sealed class Serializer<T>
    {
        /// <summary>
        /// 将指定的 Xml 格式字符串转换为 T 类型的对象
        /// </summary>
        /// <param name="xmlString">要进行反序列化的 Xml 格式字符串</param>
        /// <returns>反序列化的对象</returns>
        public static T Deserialize(string xmlString)
        {
            try
            {
                StringReader reader = new StringReader(xmlString);
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                return (T)serializer.Deserialize(reader);
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 将指定的 Xml 读取器对象转换为 T 类型的对象
        /// </summary>
        /// <param name="xmlReader">要进行反序列化的 Xml 读取器</param>
        /// <returns>反序列化的对象</returns>
        public static T Deserialize(XmlReader xmlReader)
        {
            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                return (T)serializer.Deserialize(xmlReader, "UTF-8");
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 将指定的字节序列转换为 T 类型的对象
        /// </summary>
        /// <param name="stream">要进行反序列化的字节序列</param>
        /// <returns>反序列化的对象</returns>
        public static T Deserialize(Stream stream)
        {
            try
            {

                XmlSerializer serializer = new XmlSerializer(typeof(T));
                return (T)serializer.Deserialize(stream);
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 将指定的字节数组转换为 T 类型的对象
        /// </summary>
        /// <param name="buffer">要进行反序列化的字节数组</param>
        /// <returns>反序列化的对象</returns>
        public static T Deserialize(byte[] buffer)
        {
            try
            {
                MemoryStream stream = new MemoryStream(buffer);
                return Deserialize(stream);
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 将指定的文件转换为 T 类型的对象
        /// </summary>
        /// <param name="path">要进行反序列化的文件的相对路径或绝对路径</param>
        /// <param name="mode">FileMode 常数，确定如何打开文件</param>
        /// <returns>反序列化的对象</returns>
        public static T Deserialize(string path, FileMode mode)
        {
            try
            {
                using (FileStream stream = new FileStream(path, mode))
                {
                    return Deserialize(stream);
                }
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 将指定的对象序列化为 Xml 格式字符串
        /// </summary>
        /// <param name="instance">T 类型对象实例</param>
        /// <returns>一个字符串，它表示已序列化的对象</returns>
        public static string ToString(T instance)
        {
            try
            {
                StringWriter writer = new StringWriter();
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                serializer.Serialize(writer, instance);
                return writer.ToString();
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 将指定的对象序列化为 Xml 编写器
        /// </summary>
        /// <param name="instance">T 类型对象实例</param>
        /// <returns>一个 XmlWriter，它表示已序列化的对象</returns>
        public static XmlWriter ToXmlWriter(T instance)
        {
            try
            {
                using (Stream stream = ToStream(instance))
                {
                    XmlWriter writer = XmlWriter.Create(stream);
                    return writer;
                }
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 将指定的对象序列化为字节序列
        /// </summary>
        /// <param name="instance">T 类型对象实例</param>
        /// <returns>一个 Stream，它表示已序列化的对象</returns>
        public static Stream ToStream(T instance)
        {
            try
            {
                MemoryStream stream = new MemoryStream();
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                serializer.Serialize(stream, instance);
                return stream;
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 将指定的对象序列化为字节数组
        /// </summary>
        /// <param name="instance">T 类型对象实例</param>
        /// <returns>一个字节数组，它表示已序列化的对象</returns>
        public static byte[] ToArray(T instance)
        {
            try
            {
                using (MemoryStream stream = ToStream(instance) as MemoryStream)
                {
                    return stream.ToArray();
                }
            }
            catch
            {
                throw;
            }
        }

        /// <summary>
        /// 将指定的对象序列化为文件
        /// </summary>
        /// <param name="instance">T 类型对象实例</param>
        /// <param name="path">序列化文件的相对路径或绝对路径</param>
        /// <param name="mode">FileMode 常数，确定如何打开或创建文件</param>
        public static void ToFile(T instance, string path, FileMode mode)
        {
            FileStream stream = null;
            try
            {
                stream = new FileStream(path, mode);
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                serializer.Serialize(stream, instance);
                stream.Flush();
                stream.Close();
            }
            catch
            {
                throw;
            }
            finally
            {
                stream.Dispose();
            }
        }
    }
}
